﻿#region - 版 本 注 释 -
/*----------------------------------------------------------------
 * 版权所有 (c) 2024   保留所有权利。
 * CLR版本：4.0.30319.42000
 * 机器名称：DESKTOP-GLJ2Q8J
 * 公司名称：
 * 命名空间：AutoCAD.EntityTool
 * 唯一标识：b893f674-d9d1-4fd6-88a5-6b43f5b1d8e0
 * 文件名：BlockTools
 * 当前用户域：DESKTOP-GLJ2Q8J
 * 
 * 创建者：Guo-79991
 * 电子邮箱：799919859@qq.com
 * 创建时间：2024/7/15 12:05:36
 * 版本：V1.0.0
 *
 * 功能描述(Description):
 * 参考文档(Reference):
 * 数据表(Tables):
 * 作者(Author):Guo
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/
#endregion - 版 本 注 释 -

namespace AutoCAD.EntityTool
{
    /// <summary>
    /// 表示动态属性的类型
    /// </summary>
    public enum DynamicBlockPropertyTypeCode
    {
        String = 1,  //字符串
        Real = 40,  //实数
        Short = 70,  // 短整型
        Long = 90,  //长整型
    }
    public static class BlockTools
    {
        ///// <summary>
        ///// 创建一个块并添加到数据库中
        ///// </summary>
        ///// <param name="db">图形数据库</param>
        ///// <param name="blockName">块名</param>
        ///// <param name="ents">实体列表</param>
        ///// <returns>块表记录的Id</returns>
        //public static ObjectId AddBlockTableRecord(this Database db, string blockName, List<Entity> ents)
        //{
        //    if (ents.Count <= 0)
        //        return ObjectId.Null;
        //    //打开块表
        //    var bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
        //    if (!bt.Has(blockName))  //判断是否存在名为blockName的块
        //    {
        //        //创建一个BlockTableRecord类的对象，表示索要创建的块
        //        var btr = new BlockTableRecord();
        //        //设置块名
        //        btr.Name = blockName;
        //        //将列表中的实体加入到新建的BlockTableRecord对象
        //        ents.ForEach(ent => btr.AppendEntity(ent));
        //        //切换块表为写的状态
        //        bt.UpgradeOpen();
        //        //在块表中加入blockName块
        //        bt.Add(btr);
        //        //通知事物处理
        //        db.TransactionManager.AddNewlyCreatedDBObject(btr, true);
        //        //为了安全，将块表状态改为读
        //        bt.DowngradeOpen();
        //    }

        //    //返回块表记录的Id
        //    return bt[blockName];
        //}












        /// <summary>
        /// 创建一个块并添加到数据库中
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="blockName">块名</param>
        /// <param name="ents">实体列表</param>
        /// <returns>块表记录的Id，失败返回ObjectId.Null</returns>
        public static ObjectId AddBlockTableRecord(this Database db, string blockName, List<Entity> ents)
        {
            // 参数验证
            if (db == null)
            {
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n错误：数据库不能为null");
                return ObjectId.Null;
            }

            if (string.IsNullOrWhiteSpace(blockName))
            {
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n错误：块名称不能为空");
                return ObjectId.Null;
            }

            if (ents == null || ents.Count == 0)
            {
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n错误：实体列表不能为空");
                return ObjectId.Null;
            }

            // 检查块名称是否有效
            if (!IsValidBlockName(blockName))
            {
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n错误：块名称 '{blockName}' 无效");
                return ObjectId.Null;
            }

            Transaction tr = null;
            try
            {
                tr = db.TransactionManager.StartTransaction();

                // 打开块表
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                if (bt == null)
                {
                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n错误：无法获取块表");
                    return ObjectId.Null;
                }

                ObjectId blockId = ObjectId.Null;

                // 检查块是否已存在
                if (bt.Has(blockName))
                {
                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n警告：块 '{blockName}' 已存在，返回现有块ID");
                    blockId = bt[blockName];
                }
                else
                {
                    // 创建新的块表记录
                    BlockTableRecord btr = new BlockTableRecord();
                    btr.Name = blockName;

                    // 将实体添加到块中
                    int validEntityCount = 0;
                    foreach (Entity ent in ents)
                    {
                        if (ent != null && IsEntityValidForBlock(ent, db))
                        {
                            // 关键修改：克隆不在当前数据库中的实体
                            Entity entityToAdd = ent;

                            // 如果实体已经在数据库中，需要克隆它
                            if (ent.ObjectId.IsValid && !ent.ObjectId.IsNull)
                            {
                                // 检查实体是否属于当前数据库
                                if (ent.Database != db)
                                {
                                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n警告：实体来自不同的数据库，将创建副本");
                                    entityToAdd = (Entity)ent.Clone();
                                }
                                else
                                {
                                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n警告：实体已存在于数据库中，将创建副本");
                                    entityToAdd = (Entity)ent.Clone();
                                }
                            }

                            btr.AppendEntity(entityToAdd);
                            validEntityCount++;
                        }
                        else
                        {
                            Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n警告：跳过无效实体");
                        }
                    }

                    // 检查块中是否有有效实体
                    if (validEntityCount == 0)
                    {
                        Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage("\n错误：块中没有有效实体");
                        return ObjectId.Null;
                    }

                    // 将块表记录添加到块表
                    bt.UpgradeOpen();
                    blockId = bt.Add(btr);
                    tr.AddNewlyCreatedDBObject(btr, true);

                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n成功创建块: {blockName}，包含 {validEntityCount} 个实体");
                }

                tr.Commit();
                return blockId;
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                tr?.Abort();
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\nCAD错误：{ex.Message}");
                return ObjectId.Null;
            }
            catch (System.Exception ex)
            {
                tr?.Abort();
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n系统错误：{ex.Message}");
                return ObjectId.Null;
            }
            finally
            {
                tr?.Dispose();
            }
        }




        /// <summary>
        /// 检查实体是否适合添加到块中
        /// </summary>
        private static bool IsEntityValidForBlock(Entity entity, Database targetDb)
        {
            if (entity == null)
                return false;

            try
            {
                // 检查实体是否已被处置
                var test = entity.Color;

                // 检查实体是否已经在目标数据库中
                if (entity.ObjectId.IsValid && !entity.ObjectId.IsNull)
                {
                    // 如果实体已经在目标数据库中，需要特殊处理
                    // 这种情况下通常需要克隆实体
                    return true; // 仍然返回true，因为可以通过克隆解决
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 检查块名称是否有效
        /// </summary>
        private static bool IsValidBlockName(string blockName)
        {
            if (string.IsNullOrWhiteSpace(blockName))
                return false;

            // 块名称不能包含某些特殊字符
            char[] invalidChars = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
            if (blockName.IndexOfAny(invalidChars) >= 0)
                return false;

            // 块名称不能太长（AutoCAD限制通常为255字符）
            if (blockName.Length > 255)
                return false;

            // 不能使用系统保留名称
            string[] reservedNames = { "*MODEL_SPACE", "*PAPER_SPACE", "*PAPER_SPACE0" };
            if (reservedNames.Contains(blockName.ToUpper()))
                return false;

            return true;
        }
        /// <summary>
        /// 检查实体是否有效
        /// </summary>
        private static bool IsEntityValid(Entity entity)
        {
            if (entity == null)
                return false;

            // 检查实体是否已被处置
            try
            {
                // 尝试访问一个简单属性来检查实体状态
                var test = entity.Color;
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 检查实体是否有效（替代方法）
        /// </summary>
        private static bool IsEntityValid2(Entity entity)
        {
            if (entity == null)
                return false;

            // 另一种检查方法：使用ObjectId的状态
            if (entity.ObjectId.IsValid && !entity.ObjectId.IsErased && !entity.ObjectId.IsNull)
            {
                return true;
            }

            return false;
        }



        ///// <summary>
        ///// 检查块名称是否有效
        ///// </summary>
        //private static bool IsValidBlockName(string blockName)
        //{
        //    if (string.IsNullOrWhiteSpace(blockName))
        //        return false;

        //    // 块名称不能包含某些特殊字符
        //    char[] invalidChars = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
        //    if (blockName.IndexOfAny(invalidChars) >= 0)
        //        return false;

        //    // 块名称不能太长（AutoCAD限制通常为255字符）
        //    if (blockName.Length > 255)
        //        return false;

        //    // 不能使用系统保留名称
        //    string[] reservedNames = { "*MODEL_SPACE", "*PAPER_SPACE", "*PAPER_SPACE0" };
        //    if (reservedNames.Contains(blockName.ToUpper()))
        //        return false;

        //    return true;
        //}

        ///// <summary>
        ///// 从当前选择集创建块
        ///// </summary>
        ///// <param name="db">图形数据库</param>
        ///// <param name="blockName">块名</param>
        ///// <param name="basePoint">基点</param>
        ///// <returns>块表记录的Id，失败返回ObjectId.Null</returns>
        //public static ObjectId CreateBlockFromSelection(this Database db, string blockName, Point3d basePoint)
        //{
        //    Document doc = Application.DocumentManager.MdiActiveDocument;
        //    Editor ed = doc.Editor;

        //    try
        //    {
        //        // 选择要创建块的实体
        //        PromptSelectionResult selResult = ed.GetSelection();
        //        if (selResult.Status != PromptStatus.OK)
        //            return ObjectId.Null;

        //        // 获取选择的实体
        //        List<Entity> entities = selResult.Value.GetObjectIds()
        //            .Select(id => doc.GetEntity<Entity>(id , OpenMode.ForRead))
        //            .Where(ent => ent != null)
        //            .ToList();

        //        if (entities.Count == 0)
        //        {
        //            ed.WriteMessage("\n未选择有效实体");
        //            return ObjectId.Null;
        //        }

        //        // 将实体移动到基点相对位置
        //        Vector3d moveVector = basePoint.GetVectorTo(new Point3d(0, 0, 0));
        //        Matrix3d transform = Matrix3d.Displacement(moveVector);

        //        foreach (Entity ent in entities)
        //        {
        //            ent.UpgradeOpen();
        //            ent.TransformBy(transform);
        //        }

        //        // 创建块
        //        return db.AddBlockTableRecord(blockName, entities);
        //    }
        //    catch (System.Exception ex)
        //    {
        //        ed.WriteMessage($"\n错误: {ex.Message}");
        //        return ObjectId.Null;
        //    }
        //}















        /// <summary>
        /// 从当前选择集创建块
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="blockName">块名</param>
        /// <param name="basePoint">基点</param>
        /// <returns>块表记录的Id，失败返回ObjectId.Null</returns>
        public static ObjectId CreateBlockFromSelection(this Database db, string blockName, Point3d basePoint)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            Transaction tr = null;
            try
            {
                // 选择要创建块的实体
                PromptSelectionResult selResult = ed.GetSelection();
                if (selResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                tr = db.TransactionManager.StartTransaction();

                // 获取选择的实体
                List<Entity> entities = new List<Entity>();
                foreach (ObjectId id in selResult.Value.GetObjectIds())
                {
                    Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                    if (ent != null)
                    {
                        entities.Add(ent);
                    }
                }

                if (entities.Count == 0)
                {
                    ed.WriteMessage("\n未选择有效实体");
                    tr.Commit();
                    return ObjectId.Null;
                }

                // 创建实体副本用于块创建（避免修改原始实体）
                List<Entity> entitiesForBlock = new List<Entity>();
                Vector3d moveVector = basePoint.GetVectorTo(Point3d.Origin);
                Matrix3d transform = Matrix3d.Displacement(moveVector);

                foreach (Entity ent in entities)
                {
                    // 克隆实体并应用变换
                    Entity clonedEnt = (Entity)ent.Clone();
                    clonedEnt.TransformBy(transform);
                    entitiesForBlock.Add(clonedEnt);
                }

                // 创建块
                ObjectId blockId = db.AddBlockTableRecord(blockName, entitiesForBlock);
                tr.Commit();
                return blockId;
            }
            catch (System.Exception ex)
            {
                tr?.Abort();
                ed.WriteMessage($"\n错误: {ex.Message}");
                return ObjectId.Null;
            }
            finally
            {
                tr?.Dispose();
            }
        }

        /// <summary>
        /// 创建带有属性的块
        /// </summary>
        //public static ObjectId AddBlockWithAttributes(this Database db, string blockName, List<Entity> ents, Dictionary<string, string> attributes)
        //{
        //    if (ents == null || attributes == null)
        //        return ObjectId.Null;

        //    Transaction tr = null;
        //    try
        //    {
        //        tr = db.TransactionManager.StartTransaction();

        //        // 创建块表记录
        //        BlockTableRecord btr = new BlockTableRecord();
        //        btr.Name = blockName;

        //        // 添加几何实体
        //        foreach (Entity ent in ents)
        //        {
        //            if (ent != null)
        //            {
        //                btr.AppendEntity(ent);
        //            }
        //        }

        //        // 添加属性定义
        //        double yOffset = 0;
        //        foreach (var attr in attributes)
        //        {
        //            AttributeDefinition attDef = new AttributeDefinition
        //            {
        //                Tag = attr.Key,
        //                TextString = attr.Value,
        //                Position = new Point3d(0, yOffset, 0),
        //                Height = 2.5,
        //                Visible = true
        //            };
        //            yOffset -= 5; // 每个属性向下偏移

        //            btr.AppendEntity(attDef);
        //        }

        //        // 添加到块表
        //        BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
        //        ObjectId blockId = bt.Add(btr);
        //        tr.AddNewlyCreatedDBObject(btr, true);

        //        tr.Commit();
        //        return blockId;
        //    }
        //    catch (System.Exception ex)
        //    {
        //        tr?.Abort();
        //        Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n错误: {ex.Message}");
        //        return ObjectId.Null;
        //    }
        //    finally
        //    {
        //        tr?.Dispose();
        //    }
        //}










        /// <summary>
        /// 创建带有属性的块（增强版）
        /// </summary>
        public static ObjectId AddBlockWithAttributesEx(this Database db, string blockName,
            List<Entity> ents, Dictionary<string, string> attributes,
            Point3d basePoint = default, bool overwriteExisting = false)
        {
            if (ents == null || attributes == null || string.IsNullOrEmpty(blockName))
                return ObjectId.Null;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;

                    // 处理已存在的块
                    if (bt.Has(blockName))
                    {
                        if (overwriteExisting)
                        {
                            // 删除现有块
                            ObjectId existingBlockId = bt[blockName];
                            BlockTableRecord existingBtr = tr.GetObject(existingBlockId, OpenMode.ForWrite) as BlockTableRecord;
                            existingBtr.Erase(true);
                        }
                        else
                        {
                            return bt[blockName];
                        }
                    }

                    BlockTableRecord btr = new BlockTableRecord();
                    btr.Name = blockName;

                    // 设置基点
                    if (basePoint != default)
                    {
                        btr.Origin = basePoint;
                    }

                    // 处理实体添加
                    ProcessEntitiesForBlock(ents, btr, tr , db);

                    // 添加属性定义
                    AddAttributeDefinitions(attributes, btr, tr, basePoint, db);

                    // 添加到数据库
                    ObjectId blockId = bt.Add(btr);
                    tr.AddNewlyCreatedDBObject(btr, true);

                    tr.Commit();
                    return blockId;
                }
                catch (System.Exception ex)
                {
                    tr.Abort();
                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n错误: {ex.Message}");
                    return ObjectId.Null;
                }
            }
        }

        /// <summary>
        /// 处理实体添加到块
        /// </summary>
        private static void ProcessEntitiesForBlock(List<Entity> ents, BlockTableRecord btr, Transaction tr , Database db)
        {
            foreach (Entity ent in ents.Where(e => e != null))
            {
                try
                {
                    if (ent.IsNewObject)
                    {
                        // 新实体
                        btr.AppendEntity(ent);
                        tr.AddNewlyCreatedDBObject(ent, true);
                    }
                    else if (ent.IsErased)
                    {
                        // 已删除的实体，跳过
                        continue;
                    }
                    else
                    {
                        // 已存在的实体，创建深拷贝
                        Entity clonedEnt = CreateDeepCopy(ent , db);
                        if (clonedEnt != null)
                        {
                            btr.AppendEntity(clonedEnt);
                            tr.AddNewlyCreatedDBObject(clonedEnt, true);
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    // 记录错误但继续处理其他实体
                    Debug.WriteLine($"处理实体时出错: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 创建实体的深拷贝
        /// </summary>
        public static Entity CreateDeepCopy(Entity original, Database tempDb)
        {
            try
            {
                // 创建ObjectIdCollection
                ObjectIdCollection objectIds = new ObjectIdCollection();

                using (Transaction tr = tempDb.TransactionManager.StartTransaction())
                {
                    // 将原始实体添加到临时数据库
                    BlockTableRecord btr = tr.GetObject(tempDb.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                    Entity clonedEnt = (Entity)original.Clone();

                    btr.AppendEntity(clonedEnt);
                    tr.AddNewlyCreatedDBObject(clonedEnt, true);

                    // 添加到ObjectIdCollection
                    objectIds.Add(clonedEnt.ObjectId);

                    tr.Commit();
                }

                // 使用WblockCloneObjects进行深拷贝
                IdMapping mapping = new IdMapping();
                tempDb.WblockCloneObjects(objectIds, tempDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

                // 获取克隆后的对象
                foreach (IdPair idPair in mapping)
                {
                    if (idPair.Key == objectIds[0])
                    {
                        using (Transaction tr = tempDb.TransactionManager.StartTransaction())
                        {
                            Entity finalClone = tr.GetObject(idPair.Value, OpenMode.ForRead) as Entity;
                            return finalClone;
                        }
                    }
                }

                return null;
            }
            catch (System.Exception ex)
            {
                // 异常处理
                return (Entity)original.Clone(); // 回退到简单克隆
            }
        }

        /// <summary>
        /// 添加属性定义
        /// </summary>
        private static void AddAttributeDefinitions(Dictionary<string, string> attributes,
            BlockTableRecord btr, Transaction tr, Point3d basePoint , Database db)
        {
            double yOffset = 0;

            foreach (var attr in attributes)
            {
                try
                {
                    AttributeDefinition attDef = new AttributeDefinition
                    {
                        Tag = attr.Key,
                        TextString = attr.Value,
                        Position = new Point3d(basePoint.X, basePoint.Y + yOffset, basePoint.Z),
                        Height = 2.5,
                        Visible = true,
                        Prompt = attr.Key,
                        Justify = AttachmentPoint.BaseLeft
                    };

                    yOffset -= 5;

                    db.AddEntityToModelSpace(attDef);
                    //btr.AppendEntity(attDef);
                    //tr.AddNewlyCreatedDBObject(attDef, true);
                }
                catch (Autodesk.AutoCAD.Runtime.Exception ex)
                {
                    // 记录是哪个属性出错了
                    Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n创建属性 '{attr.Key}' 时出错: {ex.Message}");
                    // 根据情况决定是继续还是重新抛出异常
                    throw; // 如果希望失败就停止，则重新抛出
                }
            }
        }


















        /// <summary>
        /// 重载AddBlockTableRecord扩展函数，使其能接受不固定的实体对象，这样在调用该函数时就不需要生成一个实体列表了 
        /// </summary>
        /// <param name="db">图像数据库</param>
        /// <param name="blockName">块名</param>
        /// <param name="ents">实体</param>
        /// <returns>实体Id</returns>
        public static ObjectId AddBlockTableRecord(this Database db, string blockName, params Entity[] ents)
        {
            return AddBlockTableRecord(db, blockName, ents.ToList());
        }
        /// <summary>
        /// 在Cad图形中插入参照块
        /// </summary>
        /// <param name="spaceId">表示块参照要加入的模型空间或图纸空间的Id</param>
        /// <param name="layer">块参照要加入的图层名</param>
        /// <param name="blockName">块参照所属的块名</param>
        /// <param name="position">插入点</param>
        /// <param name="scale">缩放比例</param>
        /// <param name="rotateAngle">旋转角度</param>
        /// <returns>实体Id</returns>
        public static ObjectId InsertBlockReference(this ObjectId spaceId, string layer, string blockName, Point3d position, Scale3d scale, double rotateAngle = 0)
        {
            //存储要插入的块参照的Id
            ObjectId blockRefId;
            //获取数据库对象
            var db = spaceId.Database;
            //以读的方式打开块表
            var bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
            //如果没有blockName表示的块，则程序返回
            if (!bt.Has(blockName)) return ObjectId.Null;
            //以写的方式打开空间（模型空间或图纸空间）
            var space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);
            //创建一个块参照，并设置插入点
            var br = new BlockReference(position, bt[blockName]);
            //设置块参照的缩放比例
            br.ScaleFactors = scale;
            //设置块参照的层名
            br.Layer = layer;
            //设置块参照的旋转角度
            br.Rotation = rotateAngle;
            //在空间中加入创建的块参照
            blockRefId = space.AppendEntity(br);
            //通知事务处理加入创建的块参照
            db.TransactionManager.AddNewlyCreatedDBObject(br, true);
            //为了安全，将块表状态改为读
            space.DowngradeOpen();
            //返回添加的块参照的Id
            return blockRefId;
        }
        /// <summary>
        /// 块参照添加属性实体
        /// </summary>
        /// <param name="blockId">块表</param>
        /// <param name="atts">要加入的块属性列表</param>
        public static void AddAttributeToBlock(this ObjectId blockId, List<AttributeDefinition> atts)
        {
            //获取数据库对象
            var db = blockId.Database;
            //打开块表记录为写的状态
            var btr = (BlockTableRecord)blockId.GetObject(OpenMode.ForWrite);
            //遍历属性定义对象列表
            foreach (var att in atts)
            {
                //为块表记录添加属性
                btr.AppendEntity(att);
                //通知事务处理
                db.TransactionManager.AddNewlyCreatedDBObject(att, true);
            }
            //为了安全，将块表记录的状态改为读
            btr.DowngradeOpen();
        }
        /// <summary>
        /// 重载AddAttributeToBlock扩展函数，使其能接受不固定的属性定义对象
        /// </summary>
        /// <param name="blockId"></param>
        /// <param name="atts"></param>
        public static void AddAttributeToBlock(this ObjectId blockId, params AttributeDefinition[] atts)
        {
            blockId.AddAttributeToBlock(atts.ToList());
        }
        /// <summary>
        /// Cad图形中插入带属性的块参照
        /// </summary>
        /// <param name="spaceId">块参照要加入的模型空间或图纸空间的Id</param>
        /// <param name="layer">块参照要加入的图层名</param>
        /// <param name="blockName">块参照所属的块名</param>
        /// <param name="position">插入点</param>
        /// <param name="scale">缩放比例</param>
        /// <param name="rotateAngle">旋转角度</param>
        /// <param name="attNameValues">表示属性的名称与取值</param>
        /// <returns>实体Id</returns>
        public static ObjectId InsertBlockReference(this ObjectId spaceId, string layer, string blockName, Point3d position, Scale3d scale, double rotateAngle, Dictionary<string, string> attNameValues)
        {
            //获取数据库对象
            var db = spaceId.Database;
            //以读的方式打开块表
            var bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForWrite);
            //如果没有blockName表示的块，则程序返回
            if (!bt.Has(blockName)) return ObjectId.Null;
            //以写的方式打开空间（模型空间或图纸空间）
            var space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForRead);
            //获取块表记录Id
            var btrId = bt[blockName];
            //打开块表记录
            var record = (BlockTableRecord)btrId.GetObject(OpenMode.ForRead);
            //创建一个块参照并设置插入点
            var br = new BlockReference(position, bt[blockName]);
            //设置块参照的缩放比例
            br.ScaleFactors = scale;
            //设置块参照的层名
            br.Layer = layer;
            //设置块参照的旋转角度
            br.Rotation = rotateAngle;
            //为了安全，将块表状态改为读
            space.AppendEntity(br);
            //判断块表记录是否包含属性定义
            if (record.HasAttributeDefinitions)
            {
                //若包含属性定义，则遍历属性定义
                foreach (var id in record)
                {
                    //检查是否是属性定义
                    var attDef = id.GetObject(OpenMode.ForRead) as AttributeDefinition;
                    if (attDef != null)
                    {
                        //创建一个新的属性对象
                        var attribute = new AttributeReference();
                        //从属性定义获得属性对象的对象特征
                        attribute.SetAttributeFromBlock(attDef, br.BlockTransform);
                        //设置属性对象的其他特征
                        attribute.Position = attDef.Position.TransformBy(br.BlockTransform);
                        attribute.Rotation = attDef.Rotation;
                        attribute.AdjustAlignment(db);
                        //判断是否包含指定的属性名称
                        if (attNameValues.ContainsKey(attDef.Tag.ToUpper()))
                        {
                            //设置属性值
                            attribute.TextString = attNameValues[attDef.Tag.ToUpper()].ToString();
                        }
                        //向块参照添加属性对象
                        br.AttributeCollection.AppendAttribute(attribute);
                        db.TransactionManager.AddNewlyCreatedDBObject(attribute, true);
                    }
                }
            }
            db.TransactionManager.AddNewlyCreatedDBObject(br, true);
            return br.ObjectId;  //返回添加的块参照的Id4
        }
        /// <summary>
        /// 更新块参照中的属性值
        /// </summary>
        /// <param name="blockRefId">块参照Id</param>
        /// <param name="attNameValues">需要更新的属性名称与取值</param>
        /// <param name="transaction">事务对象（可选）</param>
        public static void UpdateAttributeInBlock(this ObjectId blockRefId,
            Dictionary<string, string> attNameValues, Transaction transaction = null)
        {
            if (blockRefId.IsNull || !blockRefId.IsValid || blockRefId.IsErased)
                throw new ArgumentException("无效的块参照ID");

            if (attNameValues == null || attNameValues.Count == 0)
                return;

            bool isExternalTransaction = transaction != null;
            Transaction localTransaction = null;

            try
            {
                // 处理事务
                Database db = blockRefId.Database;
                if (!isExternalTransaction)
                {
                    localTransaction = db.TransactionManager.StartTransaction();
                    transaction = localTransaction;
                }

                // 获取块参照对象
                BlockReference blockRef = transaction.GetObject(blockRefId, OpenMode.ForRead) as BlockReference;
                if (blockRef == null)
                    throw new ArgumentException("指定的ID不是有效的块参照");

                // 检查是否有属性
                if (blockRef.AttributeCollection.Count == 0)
                    return;

                // 遍历块参照中的属性
                foreach (ObjectId id in blockRef.AttributeCollection)
                {
                    AttributeReference attref = null;
                    try
                    {
                        // 获取属性引用
                        attref = transaction.GetObject(id, OpenMode.ForRead) as AttributeReference;
                        if (attref == null)
                            continue;

                        // 检查是否包含指定的属性名称（不区分大小写）
                        string tagUpper = attref.Tag.ToUpper();
                        if (attNameValues.ContainsKey(tagUpper))
                        {
                            // 切换属性对象为写的状态
                            attref.UpgradeOpen();

                            // 设置属性值
                            string newValue = attNameValues[tagUpper];
                            attref.TextString = newValue ?? string.Empty;

                            // 记录修改
                            //Trace.WriteLine($"更新属性: {attref.Tag} = {newValue}");
                        }
                    }
                    catch (System.Exception ex)
                    {
                        // 记录错误但继续处理其他属性
                        //Trace.WriteLine($"处理属性时出错: {ex.Message}");
                    }
                    finally
                    {
                        // 安全地降级打开状态
                        if (attref != null && attref.IsWriteEnabled)
                        {
                            try
                            {
                                attref.DowngradeOpen();
                            }
                            catch
                            {
                                // 忽略降级错误
                            }
                        }
                    }
                }

                // 提交本地事务
                if (!isExternalTransaction)
                {
                    localTransaction?.Commit();
                }
            }
            catch (System.Exception ex)
            {
                // 回滚本地事务
                if (!isExternalTransaction)
                {
                    localTransaction?.Abort();
                }
                throw new InvalidOperationException("更新块属性失败", ex);
            }
            finally
            {
                // 释放本地事务
                if (!isExternalTransaction)
                {
                    localTransaction?.Dispose();
                }
            }
        }






        /// <summary>
        /// 更新块属性选项
        /// </summary>
        public class UpdateAttributeOptions
        {
            public bool IgnoreCase { get; set; } = true;
            public bool CreateIfNotExists { get; set; } = false;
            public bool SkipLockedAttributes { get; set; } = true;
        }

        /// <summary>
        /// 增强版：更新块参照中的属性值
        /// </summary>
        public static bool UpdateAttributesInBlock(this ObjectId blockRefId,
            Dictionary<string, string> attNameValues,
            UpdateAttributeOptions options = null)
        {
            if (blockRefId.IsNull || !blockRefId.IsValid || blockRefId.IsErased)
                return false;

            if (attNameValues == null || attNameValues.Count == 0)
                return false;

            options = options ?? new UpdateAttributeOptions();

            Database db = blockRefId.Database;
            using (Transaction transaction = db.TransactionManager.StartTransaction())
            {
                try
                {
                    BlockReference blockRef = transaction.GetObject(blockRefId, OpenMode.ForRead) as BlockReference;
                    if (blockRef == null)
                        return false;

                    bool updated = false;

                    // 处理现有属性
                    foreach (ObjectId id in blockRef.AttributeCollection)
                    {
                        AttributeReference attref = transaction.GetObject(id, OpenMode.ForRead) as AttributeReference;
                        if (attref == null)
                            continue;

                        // 检查属性是否锁定
                        if (options.SkipLockedAttributes && attref.LockPositionInBlock)
                            continue;

                        string searchTag = options.IgnoreCase ? attref.Tag.ToUpper() : attref.Tag;

                        if (attNameValues.TryGetValue(searchTag, out string newValue))
                        {
                            try
                            {
                                attref.UpgradeOpen();
                                attref.TextString = newValue ?? string.Empty;
                                attref.DowngradeOpen();
                                updated = true;

                                // 从字典中移除已处理的属性
                                attNameValues.Remove(searchTag);
                            }
                            catch (System.Exception ex)
                            {
                                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"更新属性 {attref.Tag} 时出错: {ex.Message}");
                            }
                        }
                    }

                    // 如果需要创建不存在的属性且还有未处理的属性
                    if (options.CreateIfNotExists && attNameValues.Count > 0)
                    {
                        // 这里可以添加创建新属性的逻辑
                        // 注意：创建新属性需要更复杂的逻辑
                        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"警告: {attNameValues.Count} 个属性不存在，需要创建");
                    }

                    transaction.Commit();
                    return updated;
                }
                catch (System.Exception ex)
                {
                    transaction.Abort();
                    Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"更新块属性失败: {ex.Message}");
                    return false;
                }
            }
        }














        /// <summary>
        /// 设置属性定义的通用样式
        /// </summary>
        /// <param name="att">属性</param>
        /// <param name="invisible">属性文字的可见性</param>
        public static void SetStyleForAtt(this AttributeDefinition att, bool invisible)
        {
            //属性文字的高度
            att.Height = 0.15;
            //属性文字的水平对齐方式为居中
            att.HorizontalMode = TextHorizontalMode.TextCenter;
            //属性文字的垂直对齐方式为居中
            att.VerticalMode = TextVerticalMode.TextVerticalMid;
            //属性文字的可见性
            att.Invisible = invisible;
        }
        /// <summary>
        /// 读取块中的属性值
        /// </summary>
        /// <param name="db">图像数据库</param>
        /// <param name="blockName">块名</param>
        /// <returns>属性</returns>
        public static Dictionary<string, string> ReadDataInBlock(this Database db, string blockName)
        {
            var dic = new Dictionary<string, string>();
            using (var trans = db.TransactionManager.StartTransaction())
            {
                var bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                foreach (var btrId in bt)
                {
                    var btr = trans.GetObject(btrId, OpenMode.ForWrite) as BlockTableRecord;
                    if (btr.Name == blockName)
                    {
                        if (!btr.HasAttributeDefinitions) return dic;
                        var collection = new ObjectIdCollection();
                        collection = btr.GetBlockReferenceIds(true, false);

                        foreach (ObjectId blrId in collection)
                        {
                            var blr = trans.GetObject(blrId, OpenMode.ForWrite) as BlockReference;
                            foreach (ObjectId attId in blr.AttributeCollection)
                            {
                                var att = trans.GetObject(attId, OpenMode.ForWrite) as AttributeReference;
                                dic.Add(att.Tag, att.TextString);
                            }
                        }
                    }
                }
                return dic;
            }
        }
        /// <summary>
        /// 获取动态块的动态属性值
        /// </summary>
        /// <param name="blockId">动态快的ObjectId</param>
        /// <param name="propName">需要查找的动态属性名</param>
        /// <returns>动态属性值</returns>
        public static string GetDynamicBlockValue(this ObjectId blockId, string propName)
        {
            //用于返回动态属性值的变量
            var propValue = "";
            //获得动态块的所有动态属性
            var props = blockId.GetDynProperties();
            //遍历动态属性
            foreach (DynamicBlockReferenceProperty prop in props)
            {
                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(prop.PropertyName);        /////////
                                                                                                            //如果动态属性的名称与输入的名称相同
                if (prop.PropertyName == propName)
                {
                    //获取动态属性值并结束遍历
                    propValue = prop.Value.ToString();
                    break;
                }
            }
            //返回动态属性值
            return propValue;
        }

        /// <summary>
        /// 获取动态块的动态属性值
        /// <这个未完成错误>
        /// </这个未完成错误>
        /// </summary>
        /// <param name="propName">需要查找的动态属性名</param>
        /// <returns>动态属性值</returns>
        public static string GetDynamicBlockValue(this Database db, string blockName, string propName)
        {
            //用于返回动态属性值的变量
            var propValue = "";
            //打开块表
            var bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
            if (bt.Has(blockName))  //判断是否存在名为blockName的块
            {
                //获取当前空间
                var spaceId = db.CurrentSpaceId;
                //以写的方式打开空间
                var btr = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);
                if (btr.Name == blockName)  //找到名为blockName的块
                {
                    foreach (var id in btr)
                    {
                        //获得动态块的所有动态属性
                        var props = id.GetDynProperties();
                        //遍历动态属性
                        foreach (DynamicBlockReferenceProperty prop in props)
                        {
                            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(prop.PropertyName);
                            //如果动态属性的名称与输入的名称相同
                            if (prop.PropertyName == propName)
                            {
                                //获取动态属性值并结束遍历
                                propValue = prop.Value.ToString();
                                break;
                            }
                        }
                    }
                }
            }

            //返回动态属性值
            return propValue;
        }
        /// <summary>
        /// 获得动态块的所有动态属性
        /// </summary>
        /// <param name="blockId">动态块的ObjectId</param>
        /// <returns>动态属性</returns>
        public static DynamicBlockReferencePropertyCollection GetDynProperties(this ObjectId blockId)
        {
            //获取块参照
            var br = blockId.GetObject(OpenMode.ForRead) as BlockReference;
            //如果不是动态块，则返回
            if (br == null && !br.IsDynamicBlock) return null;
            //返回动态块的动态属性
            return br.DynamicBlockReferencePropertyCollection;
        }
        /// <summary>
        /// 设置动态块的动态属性
        /// </summary>
        /// <param name="blockId">动态块的ObjectId</param>
        /// <param name="propName">动态属性的名称</param>
        /// <param name="value">动态属性的值</param>
        public static void SetDynamicBlockValue(this ObjectId blockId, string propName, object value)
        {
            //获得动态块的所有动态属性
            var props = blockId.GetDynProperties();
            //遍历动态属性
            foreach (DynamicBlockReferenceProperty prop in props)
            {
                //如果动态属性的名称与输入的名称相同且为可读
                if (prop.ReadOnly == false && prop.PropertyName == propName)
                {
                    //判断动态属性的类型并通过类型转化设置正确的动态属性值
                    switch (prop.PropertyTypeCode)
                    {
                        //短整型
                        case (short)DynamicBlockPropertyTypeCode.Short:
                            prop.Value = Convert.ToInt16(value);
                            break;
                        //长整型
                        case (short)DynamicBlockPropertyTypeCode.Long:
                            prop.Value = Convert.ToInt64(value);
                            break;
                        //实型
                        case (short)DynamicBlockPropertyTypeCode.Real:
                            prop.Value = Convert.ToDouble(value);
                            break;
                        default:  //   其他
                            prop.Value = value;
                            break;
                    }
                    break;
                }
            }
        }
        /// <summary>
        /// 获取特定类型的所有实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <param name="mode"></param>
        /// <param name="OpenErased"></param>
        /// <returns>类型为T的实体列表</returns>
        public static List<T> GetEntsInDatabase<T>(this Database db, OpenMode mode, bool OpenErased)
            where T : Entity
        {
            var ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            //生命一个List类变量用于返回类型为T的实体列表
            var ents = new List<T>();
            //获取类型T代表DXF代码名用于构建选择集过滤器
            string dxfname = RXClass.GetClass(typeof(T)).DxfName;
            //构建选择集过滤器
            TypedValue[] values = { new TypedValue((int)DxfCode.Start, dxfname) };
            SelectionFilter filter = new SelectionFilter(values);
            //选择符合条件的所有实体
            PromptSelectionResult entSelected = ed.SelectAll(filter);
            if (entSelected.Status == PromptStatus.OK)
            {
                //循环遍历符合条件的实体
                foreach (var id in entSelected.Value.GetObjectIds())
                {
                    //将实体强制转化为T类型的对象 ， 不能将实体直接转化成泛型T，必须首先转换成object类
                    T t = (T)(object)id.GetObject(mode, OpenErased);
                    ents.Add(t);  //将实体添加到返回列表中
                }
            }
            return ents;  //返回类型为T的实体列表
        }
        /// <summary>
        /// 只需要以读的方式获取数据库中特定类型的实体
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="db">图像数据库</param>
        /// <returns>实体列表</returns>
        public static List<T> GetEntsInDatabase<T>(this Database db)
            where T : Entity
        {
            return GetEntsInDatabase<T>(db, OpenMode.ForRead, false);
        }

        /// <summary>
        /// 获取特定类型(模型空间中)的所有实体,
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="db"></param>
        /// <param name="mode"></param>
        /// <param name="OpenErased"></param>
        /// <returns>类型为T的实体列表</returns>
        public static List<T> GetEntsInModelSpace<T>(this Database db, OpenMode mode, bool OpenErased)
            where T : Entity
        {
            var ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            //生命一个List类变量用于返回类型为T的实体列表
            var ents = new List<T>();
            //获取类型T代表DXF代码名用于构建选择集过滤器
            string dxfname = RXClass.GetClass(typeof(T)).DxfName;
            //构建选择集过滤器
            TypedValue[] values = { new TypedValue((int)DxfCode.Start, dxfname),
                new TypedValue((int) DxfCode.LayoutName,"Model") };
            SelectionFilter filter = new SelectionFilter(values);
            //选择符合条件的所有实体
            PromptSelectionResult entSelected = ed.SelectAll(filter);
            if (entSelected.Status == PromptStatus.OK)
            {
                //循环遍历符合条件的实体
                foreach (var id in entSelected.Value.GetObjectIds())
                {
                    //将实体强制转化为T类型的对象 ， 不能将实体直接转化成泛型T，必须首先转换成object类
                    T t = (T)(object)id.GetObject(mode, OpenErased);
                    ents.Add(t);  //将实体添加到返回列表中
                }
            }
            return ents;  //返回类型为T的实体列表
        }
        /// <summary>
        /// 获取特定类型(模型空间中)的所有实体,
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <param name="mode"></param>
        /// <param name="OpenErased"></param>
        /// <returns>类型为T的实体列表</returns>
        public static List<T> GetEntsInModelSpaces<T>(this Database db, OpenMode mode, bool OpenErased)
            where T : BlockReference
        {
            var ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            //生命一个List类变量用于返回类型为T的实体列表
            var ents = new List<T>();
            //获取类型T代表DXF代码名用于构建选择集过滤器
            string dxfname = RXClass.GetClass(typeof(T)).DxfName;
            //构建选择集过滤器
            TypedValue[] values = { new TypedValue((int)DxfCode.Start, dxfname),
                new TypedValue((int) DxfCode.LayoutName,"Model") };
            SelectionFilter filter = new SelectionFilter(values);
            //选择符合条件的所有实体
            PromptSelectionResult entSelected = ed.SelectAll(filter);
            if (entSelected.Status == PromptStatus.OK)
            {
                //循环遍历符合条件的实体
                foreach (var id in entSelected.Value.GetObjectIds())
                {
                    //将实体强制转化为T类型的对象 ， 不能将实体直接转化成泛型T，必须首先转换成object类
                    T t = (T)(object)id.GetObject(mode, OpenErased);
                    ents.Add(t);  //将实体添加到返回列表中
                }
            }
            return ents;  //返回类型为T的实体列表
        }
        /// <summary>
        /// 获取特定类型的所有实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <param name="mode"></param>
        /// <param name="OpenErased"></param>
        /// <returns>类型为T的实体列表</returns>
        public static List<T> GetSelections<T>(this Database db, OpenMode mode, bool OpenErased)
            where T : Entity
        {
            var ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            //生命一个List类变量用于返回类型为T的实体列表
            var ents = new List<T>();
            //获取类型T代表DXF代码名用于构建选择集过滤器
            string dxfname = RXClass.GetClass(typeof(T)).DxfName;
            //构建选择集过滤器
            TypedValue[] values = { new TypedValue((int)DxfCode.Start, dxfname) };
            SelectionFilter filter = new SelectionFilter(values);
            //选择符合条件的所有实体
            PromptSelectionResult entSelected = ed.GetSelection(filter);
            if (entSelected.Status == PromptStatus.OK)
            {
                //循环遍历符合条件的实体
                foreach (var id in entSelected.Value.GetObjectIds())
                {
                    //将实体强制转化为T类型的对象 ， 不能将实体直接转化成泛型T，必须首先转换成object类
                    T t = (T)(object)id.GetObject(mode, OpenErased);
                    ents.Add(t);  //将实体添加到返回列表中
                }
            }
            return ents;  //返回类型为T的实体列表
        }



        /// <summary>
        /// 获取动态块/非动态块的块名
        /// </summary>
        /// <param name="bref">块参照对象，用于获取块名</param>
        /// <returns>返回块名字符串，如果块参照不存在则返回null</returns>
        public static string GetBlockName(this BlockReference bref)
        {
            string blockName;  //存储块名
            if (bref == null) return null;  //如果块参照不存在，则返回
            if (bref.IsDynamicBlock)  //如果是动态块
            {
                ObjectId idDyn = bref.DynamicBlockTableRecord;  //获取动态块所属的动态块表记录
                                                                //打开动态块表记录
                BlockTableRecord btr = (BlockTableRecord)idDyn.GetObject(OpenMode.ForRead);
                blockName = btr.Name; //获取块名
            }
            else  //非动态块
            {
                blockName = bref.Name;  //获取块名
            }
            return blockName;  //返回块名
        }

        /// <summary>
        /// 动态块的读取(Dwg)
        /// </summary>
        /// <param name="blockDWGName">dwg文件名</param>
        /// <param name="blockName">动态块名</param>
        public static void InitialZwBlockReference(this string blockDWGName, string blockName)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            string fileName = $"{blockDWGName}.dwg";
            ObjectIdCollection oids = new ObjectIdCollection();
            ObjectIdCollection newoids = new ObjectIdCollection();
            IdMapping idMap = new IdMapping();
            //将动态块拷贝到当前document，生成块定义
            using (Database db2 = new Database(false, false))
            {
                db2.ReadDwgFile(fileName, System.IO.FileShare.Read, true, null);
                db2.CloseInput(true);
                using (Transaction tr = db2.TransactionManager.StartTransaction())
                {
                    BlockTable blockTbl = tr.GetObject(db2.BlockTableId, OpenMode.ForRead) as BlockTable;
                    BlockTableRecord modelSpace1 = tr.GetObject(blockTbl[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
                    foreach (ObjectId oid in modelSpace1)
                    {
                        oids.Add(oid);
                    }
                }
                db2.WblockCloneObjects(oids, db.CurrentSpaceId, idMap, DuplicateRecordCloning.Ignore, false);
                foreach (ObjectId oid in oids)
                {
                    try
                    {
                        if (!newoids.Contains(idMap[oid].Value))
                        {
                            newoids.Add(idMap[oid].Value);
                        }
                    }
                    catch { }

                }
            }
            //设置显示的值
            using (DocumentLock dl = doc.LockDocument())
            {
                using (Transaction trans = doc.TransactionManager.StartTransaction())
                {
                    Entity ent = trans.GetObject(newoids[0], OpenMode.ForWrite) as Entity;
                    if (ent is BlockReference)
                    {
                        CheckBlockPropertyValue((BlockReference)ent, blockName);
                    }
                    //trans.Commit();
                }
            }
        }
        /// <summary>
        /// 根据想要显示的值去显示
        /// </summary>
        /// <param name="br">块参照对象</param>
        /// <param name="blockName">块名</param>
        public static void CheckBlockPropertyValue(this BlockReference br, string blockName)
        {
            DynamicBlockReferencePropertyCollection properties = br.DynamicBlockReferencePropertyCollection;
            for (int i = 0; i < properties.Count; i++)
            {
                DynamicBlockReferenceProperty property = properties[i];
                foreach (object item in property.GetAllowedValues())
                {
                    if (item.ToString() == blockName)
                    {
                        property.Value = item;
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// 修改动态块属性
        /// </summary>
        /// <param name="blockName">动态块名</param>
        /// <param name="paramName">修改的属性名</param>
        /// <param name="paramValue">修改的属性值</param>
        /// <param name="trans">事物</param>
        public static void ModifyDynamicBlockParameter(this string blockName, string paramName, object paramValue, Transaction trans)
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;

            //获取当前块的所有引用块
            ObjectIdCollection ids = new ObjectIdCollection();

            ObjectId btrId = db.CurrentSpaceId.GetObject(OpenMode.ForWrite).ObjectId;

            BlockTableRecord btr = trans.GetObject(btrId, OpenMode.ForWrite) as BlockTableRecord;
            //var btr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;

            foreach (ObjectId entId in btr)
            {
                var ent = trans.GetObject(entId, OpenMode.ForRead) as BlockReference;
                if (ent is BlockReference && ent.Name == blockName)
                {
                    //BlockReference br = ent as BlockReference;
                    ids.Add(ent.ObjectId);
                }
            }


            //修改自定义参数的值
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                foreach (ObjectId id in ids)
                {
                    //获取块引用对象
                    BlockReference br = tr.GetObject(id, OpenMode.ForWrite) as BlockReference;
                    DynamicBlockReferencePropertyCollection props = br.DynamicBlockReferencePropertyCollection;

                    foreach (DynamicBlockReferenceProperty prop in props)
                    {
                        if (string.Equals(prop.PropertyName, paramName, StringComparison.CurrentCultureIgnoreCase))
                        {
                            //获取参数并修改值
                            var parameter = prop;
                            //if (parameter != null)
                            //{
                            prop.Value = paramValue;
                            break;
                            // }
                        }
                    }
                }

                tr.Commit();
            }
        }

        /// <summary>
        /// 从外部文件导入快
        /// </summary>
        /// <param name="destDb">目标数据库</param>
        /// <param name="sourceFileName">包含完整路径的外部文件名</param>
        public static void ImportBlocksFromDwg(this Database destDb, string sourceFileName)
        {
            //创建一个新的数据库对象，作为源数据库，以读入外部文件的对象
            var sourceDb = new Database();
            try
            {
                //把DWG文件读入到一个临时的数据库中
                sourceDb.ReadDwgFile(sourceFileName, System.IO.FileShare.Read, true, null);
                //创建一个变量用来存储块的ObjectId列表
                var blockIds = new ObjectIdCollection();
                //获取源数据库的事物处理管理器
                Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager;
                //在源数据库中开始事务处理
                using (var myT = tm.StartTransaction())
                {
                    //打开源数据库中的块表
                    var bt = tm.GetObject(sourceDb.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead, false) as BlockTable;
                    //遍历每个块
                    foreach (var btrId in bt)
                    {
                        var btr = tm.GetObject(btrId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead, false) as BlockTableRecord;
                        //只加入命名块和非布局块到复制列表中
                        if (!btr.IsAnonymous && !btr.IsLayout)
                        {
                            blockIds.Add(btrId);
                        }
                        btr.Dispose();
                    }
                    bt.Dispose();
                }
                //定义一个IdMapping 对象
                IdMapping mapping = new IdMapping();
                //从源数据库向目标数据库复制块表记录
                sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

            }
            catch (System.Exception ex)
            {

                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("复制错误：" + ex.Message);
            }
            sourceDb.Dispose();  //操作完成，销毁源数据库
        }

        /// <summary>
        /// 找到自定义属性的类型
        /// </summary>
        /// <param name="doc">Document</param>
        /// <param name="blockName">块名</param>
        public static void GetPropType(this Document doc, string blockName)
        {
            try
            {
                var db = doc.Database;
                var ed = doc.Editor;
                using (var trans = db.TransactionManager.StartTransaction())
                {

                    ObjectId btrId = doc.Database.CurrentSpaceId.GetObject(OpenMode.ForWrite).ObjectId;

                    //BlockTableRecord btr = trans.GetObject(btrId, OpenMode.ForWrite) as BlockTableRecord;
                    var btr = trans.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                    //获取当前块的所有引用块
                    ObjectIdCollection ids = new ObjectIdCollection();
                    foreach (ObjectId entId in btr)
                    {
                        BlockReference ent = trans.GetObject(entId, OpenMode.ForRead) as BlockReference;
                        ed.WriteMessage($"\n 块名：{ent.Name}");
                        ed.WriteMessage($"\n实际块名：{ent.BlockName.FirstOrDefault()}");

                        if (ent is BlockReference && ent.Name == blockName)         //AE_TOTAL_FRONT
                        {
                            //BlockReference br = ent as BlockReference;
                            ids.Add(ent.ObjectId);
                            ed.WriteMessage($"\n 找到了 ！！！{ent.Name}");
                        }
                    }
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        foreach (ObjectId id in ids)
                        {
                            //获取块引用对象
                            BlockReference br = tr.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite) as BlockReference;
                            DynamicBlockReferencePropertyCollection props = br.DynamicBlockReferencePropertyCollection;

                            foreach (DynamicBlockReferenceProperty prop in props)
                            {
                                if (string.Equals(prop.PropertyName, "铰链锁具可见性", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    //获取参数并修改值
                                    var parameter = prop;
                                    //if (parameter != null)
                                    //{
                                    ed.WriteMessage($"\n 参数s是：{prop.Value}!!!");
                                    ed.WriteMessage($"\n 参数s是Type：{(prop.Value).GetType()}!!!");
                                    break;
                                    // }
                                }
                            }
                            trans.Commit();
                        }
                        trans.Commit();

                    }

                }
            }
            catch (System.Exception ex)
            {

                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.Message);
            }
        }
        /// <summary>
        /// 动态快个数
        /// </summary>
        /// <param name="doc">当前文档</param>
        /// <returns></returns>
        public static double RecursionBlock(this Document doc)
        {
            try
            {
                double sum = 0.0;
                var selection = doc.Editor.GetSelectionEntity();
                using (Transaction trans = doc.Database.TransactionManager.StartTransaction())
                {
                    foreach (var objId in selection.GetObjectIds())
                    {
                        var str = objId.ObjectClass.DxfName;
                        var refBlock = trans.GetObject(objId, OpenMode.ForRead) as BlockReference;
                        var entities = GetBlockEntity(refBlock);
                        ($"共有{entities.Count}图元").CadMessage();
                        sum += entities.Count;
                    }
                }
                return sum;
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ex.Message.CadMessage();
                return 0.0;
            }

        }
        /// <summary>
        /// 递归块引用
        /// </summary>
        /// <param name="refblock">块参照</param>
        /// <returns></returns>
        private static List<Entity> GetBlockEntity(this BlockReference refblock)
        {
            List<Entity> entities = new List<Entity>();
            DBObjectCollection collection = new DBObjectCollection();
            refblock.Explode(collection);

            foreach (var obj in collection)
            {
                if (obj is BlockReference childrefBlock)
                {
                    entities.AddRange(GetBlockEntity(childrefBlock));
                }
                else
                {
                    var entity = obj as Entity;
                    if (entity == null) continue;
                    entities.Add(entity);
                }
            }
            return entities;
        }

        /// <summary>
        /// 插入一个块
        /// </summary>
        /// <param name="doc">文档</param>
        /// <param name="message">提示消息</param>
        /// <returns></returns>
        public static bool InsertBlock(this Document doc, string message = "请输入块名称")
        {
            var blockName = message.GetUserMessage();
            if (string.IsNullOrEmpty(blockName))
            {
                "取消".CadMessage();
                return false;
            }
            var basePoint = ("选择基点").GetPoint();
            if (basePoint is null)
            {
                ("取消").CadMessage();
                return false;
            }
            var db = doc.Database;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                var dbbt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                if (!dbbt.Has(blockName))
                {
                    ("当前没有该名称的块").CadMessage();
                    return false;
                }
                BlockTableRecord dbbtr = trans.GetObject(dbbt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                BlockReference refblock = new BlockReference(basePoint.Value, dbbt[blockName]);
                dbbtr.AppendEntity(refblock);
                trans.AddNewlyCreatedDBObject(refblock, true);
                trans.Commit();
            }
            return true;
        }
        /// <summary>
        /// 创建一个块
        /// </summary>
        /// <param name="doc">当前文档</param>
        /// <param name="message">提示信息</param>
        /// <returns>实体</returns>
        public static Entity CreateBlock(this Document doc, string message)
        {
            var blockName = message.GetUserMessage();
            Entity ent = null;
            var db = doc.Database;
            if (string.IsNullOrEmpty(blockName))
            {
                "未输入块名...".CadMessage();
                return null;
            }
            var basePoint = "选择基点".GetPoint();
            if (basePoint is null)
            {
                "未选择基点".CadMessage();
                return null;
            }
            var selection = doc.Editor.GetSelectionEntity();
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                var block = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                if (block.Has(blockName))
                {
                    "已存在相同名称的块".CadMessage();
                    return null;
                }
                var btr = new BlockTableRecord();
                btr.Origin = basePoint.Value;
                btr.Name = blockName;
                foreach (var objIds in selection.GetObjectIds())
                {
                    var entity = trans.GetObject(objIds, OpenMode.ForRead) as Entity;
                    var cloneEntity = entity.Clone() as Entity;
                    ent = cloneEntity;
                    btr.AppendEntity(cloneEntity);
                }
                block.UpgradeOpen();
                block.Add(btr);
                block.DowngradeOpen();
                trans.AddNewlyCreatedDBObject(btr, true);
                trans.Commit();
            }
            return ent;
        }


        #region 写入属性




        #endregion



    }
}
